#include "propertyitem.hpp"
#include "dbusargv.hpp"
PropertyItem::PropertyItem(PropertyItem *parent) : QObject(parent)
{
    parentItem=parent;
    m_isDict = 0;
    if(parentItem != Q_NULLPTR)
    {
        parentItem->childItems.append (this);
    }
}
PropertyItem::~PropertyItem()
{
    qDeleteAll(childItems);
    childItems.clear ();
}

PropertyItem *PropertyItem::getParent() const
{
    return parentItem;
}

QString PropertyItem::data(int column)
{
    if(parentItem == Q_NULLPTR)
    {
        return "";
    }
    if(column == 0)
    {
        if(parentItem->m_Type == DBUS_TYPE_STRUCT||
                parentItem->m_Type == DBUS_TYPE_ARRAR)
        {
            int index = parentItem->childItems.indexOf (this);
            return QString::number (index+1);
        }else if(parentItem->m_Type == DBUS_TYPE_DICT)
        {
            int index = parentItem->childItems.indexOf (this)/2;
            return QString::number (index+1);
        }else if(parentItem->m_Type == QMetaType::UnknownType)
        {
            return m_Name;
        }else
        {
            return "0000000000";
        }
    }else if(column == 1)
    {
        return m_TypeName;
    }else if(column == 2)
    {
        if(m_Type == DBUS_TYPE_STRUCT){
            QString ret = "(";
            if(childItems.count ()>0)
            {
                ret.append (childItems.first ()->data (2));
            }
            for (int i=1;i<childItems.count ();i++) {
                ret.append (",");
                ret.append (childItems.at (i)->data (2));
            }
            ret +=")";
            return ret;
        }
        else if(m_Type == DBUS_TYPE_ARRAR)
        {
            QString ret = "[";
            if(childItems.count ()>0)
            {
                ret.append (childItems.first ()->data (2));
            }
            for (int i=1;i<childItems.count ();i++) {
                ret.append (",");
                ret.append (childItems.at (i)->data (2));
            }
            ret +="]";
            return ret;
        }else if(m_Type == DBUS_TYPE_DICT)
        {
            QString ret = "{";
            if(childItems.count ()>0)
            {
                ret.append (childItems.first ()->data (2));
            }
            for (int i=1;i<childItems.count ();i++) {
                ret.append (",");
                ret.append (childItems.at (i)->data (2));
            }
            ret +="}";
            return ret;
        }else if(m_Type == QMetaType::UnknownType)
        {
            return "";
        }else
        {
            return m_Values;
        }

    }

    return "";
}

bool PropertyItem::setBuildItemsByDBusArg(const QString &DBusArgs)
{
    int ctype = 0;
    QString typeName = "";
    clear ();
    bool bret = getTypeByDBusArg(DBusArgs, ctype,typeName);
    if(bret)
    {
        m_Type = ctype;
        m_TypeName = DBusArgs;
        m_Subtypes.clear ();
        if(m_Type == DBUS_TYPE_STRUCT)
        {
            QString Value;
            QString out = DBusArgs.mid (1);
            while (true) {
                int  nRet = getNextType(out,Value,out);
                if(nRet<0)
                {
                    return false;
                }
                PropertyItem *item = new PropertyItem(this);
                item->setBuildItemsByDBusArg(Value);
                m_Subtypes<<item->getType ();
                //childItems.append (item);
                if(out.startsWith (")"))
                    break;
            }

        }else if(m_Type == DBUS_TYPE_ARRAR)
        {
            QString Value;
            QString out = DBusArgs.mid (1);
            int  nRet = getNextType(out,Value,out);
            if(nRet<0)
            {
                return false;
            }
            PropertyItem *item = new PropertyItem(this);
            item->setBuildItemsByDBusArg(Value);
            m_Subtypes<<item->getType ();
            //childItems.append (item);
        }else if(m_Type == DBUS_TYPE_DICT)
        {
            QString Value0,Value1;
            QString out = DBusArgs.mid (2);
            int  nRet0 = getNextType(out,Value0,out);
            int  nRet1 = getNextType(out,Value1,out);
            if(nRet0<0 || nRet1<0)
            {
                return false;
            }
            PropertyItem *item0 = new PropertyItem(this);
            item0->setBuildItemsByDBusArg(Value0);
            item0->setIsDict (1);
            m_Subtypes<<item0->getType ();
            //childItems.append (item0);
            PropertyItem *item1 = new PropertyItem(this);
            item1->setBuildItemsByDBusArg(Value1);
            item1->setIsDict (2);
            m_Subtypes<<item1->getType ();
            //childItems.append (item1);
        }
    }
}



void PropertyItem::setValues(const QString &Values)
{
    m_Values = Values;
}

bool PropertyItem::setValues(const DVariant &Values)
{
    bool ok=false;
    clear();
    m_Type = Values.type ();
    m_TypeName = Values.getArgType();
    if(m_Type == DBUS_TYPE_STRUCT)
    {
        structs d0 = Values.getStruct (&ok);
        if(!ok)
        {
            //error;
            return ok;
        }
        foreach (DVariant var, d0.Values) {
            PropertyItem *sub = new PropertyItem(this);
            if(!sub->setValues (var))
            {
                return false;
            }
            //childItems.append (sub);
        }
    }else if(m_Type == DBUS_TYPE_ARRAR)
    {
        array d0 = Values.getArray (&ok);
        if(!ok)
        {
            //error;
            return ok;
        }
        foreach (auto var, d0.Values) {
            PropertyItem *sub = new PropertyItem(this);
            if(!sub->setValues (var))
            {
                return false;
            }
            //childItems.append (sub);
        }

    }else if(m_Type == DBUS_TYPE_DICT)
    {
        dict d0 = Values.getDict (&ok);
        if(!ok)
        {
            //error;
            return false;
        }
        for (int i=0;i<d0.Values.count ();i++) {
            auto var0=d0.keys.at (i);
            auto var1=d0.Values.at (i);
            PropertyItem *subkey = new PropertyItem(this);
            if(!subkey->setValues (var0))
            {
                return false;
            }
            subkey->setIsDict (1);
            //childItems.append (subkey);
            PropertyItem *sub1 = new PropertyItem(this);
            if(!sub1->setValues (var1))
            {
                return false;
            }
            sub1->setIsDict (2);
            //childItems.append (sub1);
        }
    }else if(m_Type == qMetaTypeId<QDBusObjectPath>())
    {
       m_Values = Values.getString(&ok);
    }else if(m_Type == qMetaTypeId<QDBusSignature>())
    {
        m_Values = Values.getString(&ok);
    }else if(m_Type == qMetaTypeId<QDBusUnixFileDescriptor>())
    {
         m_Values = Values.getString(&ok);
    }else if(m_Type == qMetaTypeId<QDBusVariant>())
    {
         m_Values = Values.getString(&ok);
    }else
    {
        m_Values = Values.getString(&ok);
    }
    return true;
}

bool PropertyItem::checkDictKey(const QString &Values)
{
    if(getIsDict () == 1)
    {
        if(m_Type == DBUS_TYPE_STRUCT || m_Type == DBUS_TYPE_DICT || m_Type == DBUS_TYPE_ARRAR)
            return true;
        if(this->parentItem == Q_NULLPTR)
        {
            return true;
        }
        foreach (auto var, parentItem->childItems) {
            if(var->m_Values == Values)
            {
                return false;
            }
        }
    }
    return true;
}

bool PropertyItem::isBaseType()
{
    return m_Type <DBUS_TYPE_STRUCT;
}

DVariant PropertyItem::getValue()
{
    DVariant d;
    if(m_Type == DBUS_TYPE_STRUCT)
    {
        structs d0;
        d0.m_argTypes = m_TypeName;
        d0.m_Subtypes<<m_Subtypes;
        foreach (auto var, childItems) {
            d0.Values.append (var->getValue ());
        }
        d.setValue (d0);
    }else if(m_Type == DBUS_TYPE_ARRAR)
    {
        array d0;
        d0.m_argTypes = m_TypeName;
        d0.m_Subtypes<<m_Subtypes;
        int tyieid = 0;
        foreach (auto var, childItems) {
            d0.Values.append (var->getValue ());
        }
        d.setValue (d0);

    }else if(m_Type == DBUS_TYPE_DICT)
    {
        dict d0;
        d0.m_argTypes =m_TypeName;
        d0.m_Subtypes<<m_Subtypes;
        for (int i=0;i<childItems.count ();i+=2) {
            auto var0=childItems.at (i);
            auto var1=childItems.at (i+1);
            d0.keys.append (var0->getValue ());
            d0.Values.append (var1->getValue ());
        }
        d.setValue (d0);

    }else if(m_Type == qMetaTypeId<QDBusObjectPath>())
    {
        QDBusObjectPath d0(m_Values);
        d.setValue (d0);

    }else if(m_Type == qMetaTypeId<QDBusSignature>())
    {
        QDBusSignature d0(m_Values);
        d.setValue (d0);
    }else if(m_Type == qMetaTypeId<QDBusUnixFileDescriptor>())
    {
        QDBusUnixFileDescriptor d0(m_Values.toInt ());
        d.setValue (d0);
    }else if(m_Type == qMetaTypeId<QDBusVariant>())
    {
        QDBusVariant d0(m_Values);
        d.setValue (d0);
    }else
    {
        d.setValue(m_Values,m_Type);
    }
    return d;

}

int PropertyItem::getIsDict() const
{
    return m_isDict;
}

void PropertyItem::setIsDict(int isDict)
{
    m_isDict = isDict;
}

int PropertyItem::getType() const
{
    return m_Type;
}

void PropertyItem::setType(int Type)
{
    m_Type = Type;
}

QString PropertyItem::getName() const
{
    return m_Name;
}

void PropertyItem::setName(const QString &Name)
{
    m_Name = Name;
}

